﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FactoryMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            //Creator[] creators = new Creator[2];
            //creators[0] = new ConcreteCreator1();
            //creators[1] = new ConcreteCreator2();

            //foreach (Creator creator in creators)
            //{
            //    Product product = creator.FactoryMethod();

            //    Console.WriteLine("Created {0}",
            //        product.GetType().Name);
            //}

            // Note: constructors call Factory Method
            Document[] documents = new Document[2];
            documents[0] = new Resume();
            documents[1] = new Report();
            // Display document pages
            foreach (Document document in documents)
            {
                Console.WriteLine("\n" + document.GetType().Name + "--");
                foreach (Page page in document.Pages)
                {
                    Console.WriteLine(" " + page.GetType().Name);
                }
            }

            Console.Read();
        }
    }

    class Product
    { }
    class ConcreteProduct1 : Product
    { }
    class ConcreteProduct2 : Product
    { }
    abstract class Creator
    {
        public abstract Product FactoryMethod();
    }
    class ConcreteCreator1 : Creator
    {
        public override Product FactoryMethod()
        {
            return new ConcreteProduct1();
        }
    }
    class ConcreteCreator2 : Creator
    {
        public override Product FactoryMethod()
        {
            return new ConcreteProduct2();
        }
    }

    abstract class Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class SkillsPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class EducationPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class ExperiencePage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class IntroductionPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class ResultsPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class ConclusionPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class SummaryPage : Page
    {

    }



    /// <summary>

    /// A 'ConcreteProduct' class

    /// </summary>

    class BibliographyPage : Page
    {

    }



    /// <summary>

    /// The 'Creator' abstract class

    /// </summary>

    abstract class Document
    {

        private List<Page> _pages = new List<Page>();



        // Constructor calls abstract Factory method

        public Document()
        {

            this.CreatePages();

        }



        public List<Page> Pages
        {

            get { return _pages; }

        }



        // Factory Method

        public abstract void CreatePages();

    }



    /// <summary>

    /// A 'ConcreteCreator' class

    /// </summary>

    class Resume : Document
    {

        // Factory Method implementation

        public override void CreatePages()
        {

            Pages.Add(new SkillsPage());

            Pages.Add(new EducationPage());

            Pages.Add(new ExperiencePage());

        }

    }



    /// <summary>

    /// A 'ConcreteCreator' class

    /// </summary>

    class Report : Document
    {

        // Factory Method implementation

        public override void CreatePages()
        {

            Pages.Add(new IntroductionPage());

            Pages.Add(new ResultsPage());

            Pages.Add(new ConclusionPage());

            Pages.Add(new SummaryPage());

            Pages.Add(new BibliographyPage());

        }

    }
}
